#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MaxSize 50
typedef int Status;
typedef struct {
  char id[20];
  char name[50];
  float price;
} Book;
typedef struct {
  Book *elem;
  int length;
} BookList;

Status InitList(BookList *L);                   // 初始化
int getLength(BookList *L);                     // 顺序表长度
Status PrintAllElem(BookList *L);               // 打印所有元素
Status GetElem(BookList *L, int i, Book *book); // 取值
int SearchIndexByBookId(
    BookList *L, char *id); // 查找元素index(从1开始，返回index,没找到返回 -1)
Status InsertElem(BookList *L, int i, Book *book); // 插入元素

Status DeleteElem(BookList *L, int i); // 删除元素
char *formatStr(char str[], int i);    // 格式化字符串
float getRandomNum(float a, float b);  // 生成指定范围内的随机浮点数

int main() {
  char pre[10] = "CGZM-ID-";   // Book元素的id前缀
  srand((unsigned)time(NULL)); // 随机数种子
  BookList *L =
      (BookList *)malloc(sizeof(BookList)); // 分配空间，返回BookList类型指针
  if (L == NULL) {
    printf("内存分配失败，无法创建BookList对象\n");
    return ERROR;
  }
  InitList(L); // 初始化顺序表
  // 减少测试数量，避免潜在问题
  int insertCount = 10;                   // 测试只插入10个元素
  for (int i = 0; i < insertCount; i++) { // 为数组赋值
    // 构造将要插入的Book元素
    Book *temp =
        (Book *)malloc(sizeof(Book)); // 分配空间，返回Book类型指针 temp
    if (temp == NULL) {
      printf("内存分配失败，无法创建临时Book对象\n");
      // 返回前释放已分配的内存资源
      free(L->elem);
      free(L);
      return ERROR;
    }
    printf("正在准备插入第%d个元素...\n", i + 1);
    // 直接在main函数中格式化ID，避免使用有问题的formatStr函数
    sprintf(temp->id, "%s%03d", pre, i + 1); // 设置即将插入的Book的id
    sprintf(temp->name, "Name-%d", i + 1);   // 设置即将插入的Book的name
    temp->price = getRandomNum(80, 100);     // 设置即将插入的Book的price
    Status insertRes =
        InsertElem(L, i + 1, temp); // 插入构造好的Book元素 temp，索引从1开始
    if (insertRes != OK) {
      printf("插入第%d个元素失败，返回状态：%d\n", i + 1, insertRes);
      free(temp);
      free(L->elem);
      free(L);
      return ERROR;
    }
    free(temp); // 释放已插入的Book元素 temp
  }

  printf("插入完成，当前列表长度：%d\n", L->length);

  // 增加额外的调试信息
  printf("\n开始测试SearchIndexByBookId函数:\n");
  printf("正在查找ID为CGZM-ID-005的图书...\n");
  char searchId[20] = "CGZM-ID-005";
  int index = SearchIndexByBookId(L, searchId);
  if (index == -1) {
    printf("没有找到元素%s\n", searchId);
  } else {
    printf("找到元素%s，索引值为：%d\n", searchId, index);
  }

  //   测试查找不存在的元素
  printf("正在查找ID为CGZM-ID-999的图书...\n");
  strcpy(searchId, "CGZM-ID-999");
  index = SearchIndexByBookId(L, searchId);
  if (index == -1) {
    printf("没有找到元素%s\n", searchId);
  } else {
    printf("找到元素%s，索引值为：%d\n", searchId, index);
  }

  //   测试插入元素
  printf("正在插入ID为CGZM-ID-999的图书...\n");
  Book *temp = (Book *)malloc(sizeof(Book)); // 分配空间，返回Book类型指针 temp
  if (temp == NULL) {
    printf("内存分配失败，无法创建临时Book对象\n");
    // 返回前释放已分配的内存资源
    free(L->elem);
    free(L);
    return ERROR;
  }
  strcpy(temp->id, "CGZM-ID-999");
  strcpy(temp->name, "Name-999");
  temp->price = getRandomNum(80, 100);
  Status insertRes = InsertElem(L, L->length + 1,
                                temp); // 插入构造好的Book元素 temp，索引从1开始
  if (insertRes != OK) {
    printf("插入第11个元素失败，返回状态：%d\n", insertRes);
    free(temp);
    free(L->elem);
    free(L);
    return ERROR;
  }
  free(temp); // 释放已插入的Book元素 temp
  printf("插入完成，当前列表长度：%d\n", L->length);

  //  测试打印所有元素
  printf("\n开始打印列表所有元素:\n");
  Status printStatus = PrintAllElem(L);
  if (printStatus != OK) {
    printf("打印元素失败，返回状态：%d\n", printStatus);
  }

  // 测试删除元素
  // 删除失败示例，删除传参越界
  int deleteIndex = 112;
  Status deleteRes = DeleteElem(L, deleteIndex);
  if (deleteRes == OK) {
    printf("BookList第%d个元素删除成功\n", deleteIndex);
  } else {
    printf("BookList第%d个元素删除失败\n", deleteIndex);
  }
  // 删除成功示例(最后三个)
  Status delRes;
  for (int del = 1; del <= 3; del++) {
    int delIndex = getLength(L);
    delRes = DeleteElem(L, delIndex);
    if (delRes == OK) {
      printf("BookList第%d个元素删除成功\n", delIndex);
    } else {
      printf("BookList第%d个元素删除失败\n", delIndex);
    }
  }

  // 删除成功示例(前面三个)
  for (int del = 1; del <= 3; del++) {
    delRes = DeleteElem(L, 1);
    if (delRes == OK) {
      printf("BookList第%d个元素删除成功\n", del);
    } else {
      printf("BookList第%d个元素删除失败\n", del);
    }
  }

  PrintAllElem(L);

  // 测试取值
  Book book;
  // &book 表示取结构体变量 book 的地址，将其作为指针传入
  // GetElem，用于接收查到的元素
  Status getStatus = GetElem(L, 3, &book);
  if (getStatus != OK) {
    printf("取值失败，返回状态：%d\n", getStatus);
  } else {
    printf("成功获取索引为3的元素，ID：%s，名称：%s，价格：￥%.2f 元\n",
           book.id, book.name, book.price);
  }

  // 测试顺序表长度
  printf("顺序表长度为：%d", getLength(L));

  // book 变量本身是在栈上分配的临时结构体，未动态申请内存，无需 free
  // 释放顺序表占用的内存
  free(L->elem);
  free(L);
  return 0;
}

// 初始化
Status InitList(BookList *L) {
  L->elem = (Book *)malloc(MaxSize * sizeof(Book));
  if (L->elem == NULL) {
    printf("%s\n", "顺序表初始化失败");
    return ERROR;
  }
  L->length = 0;
  printf("%s\n", "顺序表初始化成功");
  printf("%s\n",
         "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
  return OK;
}

// 获取顺序表长度
int getLength(BookList *L) {
  if (L == NULL || L->elem == NULL) {
    printf("指针L或顺序表L->elem不存在");
    return -1;
  }

  return L->length;
}

// 打印所有元素
Status PrintAllElem(BookList *L) {
  if (L == NULL || L->elem == NULL) {
    printf("%s\n", "顺序表为空，无法打印元素");
    return ERROR;
  }
  printf("当前顺序表共%d本图书元素，具体如下：\n", L->length);
  for (int i = 0; i < L->length; i++) {
    printf("第%d本图书: ", i + 1);                      // 打印
    printf("图书ID：%s, ", L->elem[i].id);              // 打印图书ID
    printf("图书名称：%s, ", L->elem[i].name);          // 打印图书名称
    printf("图书价格：￥%.2f 元;\n", L->elem[i].price); // 打印图书价格
    if (i % 10 == 9) {                                  // 每10行打印一行分隔符
      printf("%s\n",
             "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
    }
  }
  printf("所有元素打印完毕，共%d本图书\n", L->length);
  return OK;
}

// 取值
Status GetElem(BookList *L, int i, Book *book) {
  // 参数有效性松检查
  if (L == NULL || L->elem == NULL || book == NULL) {
    return ERROR;
  }
  //   索引有效性检查
  if (i < 1 || i > L->length) {
    return ERROR;
  }
  // 复制图书信息
  strcpy(book->id, L->elem[i - 1].id);
  strcpy(book->name, L->elem[i - 1].name);
  book->price = L->elem[i - 1].price;
  return OK;
}

// 查找元素index(从1开始，返回index,没找到返回 -1)
int SearchIndexByBookId(BookList *L, char *id) {
  if (L == NULL || L->elem == NULL || id == NULL) {
    return ERROR;
  }
  for (int i = 0; i < L->length; i++) {
    if (strcmp(L->elem[i].id, id) == 0) {
      //   printf("找到id为\"%s\"的元素，索引号是：%d，书名为：\"%s\"，价格为：￥%."
      //          "2f元\n",
      //          L->elem[i].id, i + 1, L->elem[i].name, L->elem[i].price);
      return i + 1;
    }
  }
  //   printf("没有找到id为\"%s\"的元素\n", id);
  return -1;
}

// 插入元素
Status InsertElem(BookList *L, int i, Book *book) {
  if (L == NULL || L->elem == NULL || book == NULL) {
    return ERROR;
  }
  if (i < 1 || i > L->length + 1) {
    return OVERFLOW;
  }
  if (L->length == MaxSize) {
    return ERROR;
  }
  for (int j = L->length - 1; j >= i - 1; j--) {
    L->elem[j + 1] = L->elem[j];
  }
  L->elem[i - 1] = *book;
  ++L->length;
  return OK;
}

// 删除元素
Status DeleteElem(BookList *L, int i) {
  if (L == NULL || L->elem == NULL) {
    printf("DeleteElem函数，第1个参数L有误\n");
    return ERROR;
  }
  if (i < 1 || i > L->length) {
    printf("DeleteElem函数，第2个参数i有误，不在范围内\n");
    return ERROR;
  }
  for (int j = i - 1; j < L->length - 1; j++) {
    L->elem[j] = L->elem[j + 1];
  }
  --L->length;
  return OK;
}

// 格式化字符串 - 注意：此函数已经不再被使用，保留以备将来可能需要
char *formatStr(char str[], int i) {
  char result[100]; // 使用局部变量存储结果
  sprintf(result, "%s%03d", str, i);
  strcpy(str, result); // 复制结果到输出参数
  return str;
}
// 生成指定范围内的随机浮点数
float getRandomNum(float a, float b) {
  float res;
  res = a + (b - a) * ((float)rand() / RAND_MAX);
  return res;
}